package com.example.factory;

import com.example.annotatedclass.ClassAnnotatedBean;
import com.example.annotatedclass.FieldAnnotatedBean;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.annotation.processing.Filer;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import java.io.IOException;


public class FactoryGroupedClasses {
    /**
     * class
     */
    private String qualifiedClassName;
    /**
     * class bean
     */
    private ClassAnnotatedBean classAnnotatedBean;

    public FactoryGroupedClasses(ClassAnnotatedBean classAnnotatedBean) {
        this.classAnnotatedBean = classAnnotatedBean;
        this.qualifiedClassName = classAnnotatedBean.getTypeElement().getQualifiedName().toString();
    }



    /**
     * 执行器
     * @param elementUtils
     * @param filer
     * @throws IOException
     */
    public void generateCode(Elements elementUtils, Filer filer) throws IOException {
        TypeElement superClassName = elementUtils.getTypeElement(qualifiedClassName);
        String className = superClassName.getSimpleName().toString();
        PackageElement pkg = elementUtils.getPackageOf(superClassName);
        String packageName = pkg.isUnnamed() ? null : pkg.getQualifiedName().toString();
        TypeSpec.Builder typeSpec = TypeSpec.classBuilder(className);
        for (FieldAnnotatedBean fieldAnnotatedBean : classAnnotatedBean.getFieldMap()) {
            TypeElement typeName = elementUtils.getTypeElement(fieldAnnotatedBean.getQualifiedTypeClassName());
            MethodSpec method = MethodSpec.methodBuilder(getNewMethodName(fieldAnnotatedBean.getName()))
                    .addModifiers(Modifier.PUBLIC)
                    .addStatement("return $N ", fieldAnnotatedBean.getName())
                    .returns(TypeName.get(typeName.asType())).build();
            typeSpec.addMethod(method);
        }
        // Write file
        JavaFile.builder(packageName, typeSpec.build()).build().writeTo(filer);
    }

    private String getNewMethodName(String value) {
        return String.format("get" + value.substring(0, 1).toUpperCase() + value.substring(1, value.length()));
    }

    public ClassAnnotatedBean getClassAnnotatedBean() {
        return classAnnotatedBean;
    }

    public void setClassAnnotatedBean(ClassAnnotatedBean classAnnotatedBean) {
        this.classAnnotatedBean = classAnnotatedBean;
    }
}
